import {
  Document, Paragraph, TextRun, HeadingLevel, ImageRun, AlignmentType,
  Table, TableRow, TableCell, WidthType, BorderStyle, TableLayoutType,
  ExternalHyperlink, Header, Footer
} from 'docx';

// 注意：此库专为浏览器环境设计，使用原生 DOMParser 替代 cheerio

export interface HtmlToDocxOptions {
  /**
   * 页面方向
   */
  orientation?: 'portrait' | 'landscape';
  /**
   * 页边距 (以厘米为单位)
   */
  margins?: {
    top?: number;
    right?: number;
    bottom?: number;
    left?: number;
  };
  /**
   * 图片最大宽度 (像素)
   */
  maxImageWidth?: number;
  /**
   * 图片最大高度 (像素)
   */
  maxImageHeight?: number;
  /**
   * 文档属性
   */
  properties?: {
    /**
     * 创建者
     */
    creator?: string;
    /**
     * 描述
     */
    description?: string;
    /**
     * 标题
     */
    title?: string;
    /**
     * 主题
     */
    subject?: string;
    /**
     * 关键词
     */
    keywords?: string;
    /**
     * 修订版本
     */
    revision?: number;
    /**
     * 最后修改者
     */
    lastModifiedBy?: string;
  };
  /**
   * 页眉设置
   */
  header?: {
    /**
     * 页眉内容 (HTML字符串)
     */
    content?: string;
    /**
     * 页眉样式
     */
    style?: {
      /**
     * 字体大小 (半点)
     */
      fontSize?: number;
      /**
     * 字体名称
     */
      fontFamily?: string;
      /**
     * 字体颜色 (hex)
     */
      color?: string;
      /**
     * 是否粗体
     */
      bold?: boolean;
      /**
     * 是否斜体
     */
      italic?: boolean;
      /**
     * 文本对齐方式
     */
      alignment?: 'left' | 'center' | 'right';
    };
  };
  /**
   * 页脚设置
   */
  footer?: {
    /**
     * 页脚内容 (HTML字符串)
     */
    content?: string;
    /**
     * 页脚样式
     */
    style?: {
      /**
     * 字体大小 (半点)
     */
      fontSize?: number;
      /**
     * 字体名称
     */
      fontFamily?: string;
      /**
     * 字体颜色 (hex)
     */
      color?: string;
      /**
     * 是否粗体
     */
      bold?: boolean;
      /**
     * 是否斜体
     */
      italic?: boolean;
      /**
     * 文本对齐方式
     */
      alignment?: 'left' | 'center' | 'right';
    };
  };
}

/**
 * CSS 规则接口
 */
export interface CSSRule {
  selector: string;
  properties: Record<string, string>;
}

/**
 * CSS 规则集合
 */
export interface CSSRuleSet {
  [selector: string]: Record<string, string>;
}

export interface ConversionResult {
  /**
   * 生成的 DOCX 文档对象
   */
  document: Document;
  /**
   * 转换警告信息
   */
  warnings: string[];
}

/**
 * 文档元素类型（段落或表格）
 */
export type DocumentElement = Paragraph | Table;

export interface ParsedBorderStyle {
  width?: number; // 边框宽度（twips）
  style?: 'single' | 'double' | 'dotted' | 'dashed' | 'none';
  color?: string; // 边框颜色（hex）
}

export interface ParsedStyle {
  color?: string;
  fontSize?: number;
  fontFamily?: string;
  bold?: boolean;
  italic?: boolean;
  underline?: boolean;
  strikethrough?: boolean;
  indent?: number;
  characterSpacing?: number; // 字符间距缩放比例 (百分比)
  textAlign?: 'left' | 'center' | 'right' | 'justify'; // 文本对齐方式
  lineHeight?: { line: number; lineRule: string }; // 行高设置
  backgroundColor?: string; // 背景颜色
  border?: ParsedBorderStyle; // 边框样式
  borderTop?: ParsedBorderStyle;
  borderRight?: ParsedBorderStyle;
  borderBottom?: ParsedBorderStyle;
  borderLeft?: ParsedBorderStyle;
  marginTop?: number; // margin-top (twips)
  marginRight?: number; // margin-right (twips)
  marginBottom?: number; // margin-bottom (twips)
  marginLeft?: number; // margin-left (twips)
  href?: string; // 超链接地址
}

export interface ImageInfo {
  data: Buffer | Uint8Array;
  width: number;
  height: number;
  type: string;
}

/**
 * 解析 style 标签中的 CSS 规则
 * @param cssText - CSS 文本内容
 * @returns CSSRuleSet - 解析后的 CSS 规则集合
 */
function parseCSSRules(cssText: string): CSSRuleSet {
  const rules: CSSRuleSet = {};

  // 移除 CSS 注释
  const cleanCSS = cssText.replace(/\/\*[\s\S]*?\*\//g, '');

  // 分割 CSS 规则
  const ruleMatches = cleanCSS.match(/([^{]+)\{([^}]+)\}/g) || [];

  ruleMatches.forEach(rule => {
    // 提取选择器和属性
    const match = rule.match(/([^{]+)\{([^}]+)\}/);
    if (!match) return;

    const [, selector, propertiesText] = match;
    const cleanSelector = selector.trim();

    // 提取属性键值对
    const properties: Record<string, string> = {};
    const propertyMatches = propertiesText.split(';').map(p => p.trim()).filter(p => p);

    propertyMatches.forEach(property => {
      const [key, value] = property.split(':').map(p => p.trim());
      if (key && value) {
        properties[key] = value;
      }
    });

    if (cleanSelector && Object.keys(properties).length > 0) {
      rules[cleanSelector] = properties;
    }
  });

  return rules;
}

/**
 * 检测当前环境是否为浏览器
 */
function isBrowser(): boolean {
  return typeof window !== 'undefined' && typeof document !== 'undefined';
}

/**
 * 从 HTML 中提取所有 style 标签的 CSS 规则
 * @param doc - DOM 文档对象
 * @returns CSSRuleSet - 合并后的 CSS 规则集合
 */
function extractCSSRules(doc: globalThis.Document): CSSRuleSet {
  const allRules: CSSRuleSet = {};

  // 获取所有 style 标签
  const styleElements = doc.querySelectorAll('style');
  styleElements.forEach((styleElement) => {
    const cssText = styleElement.textContent || '';
    const rules = parseCSSRules(cssText);

    // 合并 CSS 规则
    Object.keys(rules).forEach(selector => {
      if (!allRules[selector]) {
        allRules[selector] = {};
      }

      // 合并属性，如果有冲突则后面的会覆盖前面的
      Object.assign(allRules[selector], rules[selector]);
    });
  });

  return allRules;
}

/**
 * 解析颜色值，支持 hex、rgb、rgba、颜色名称
 */
function parseColor(colorValue: string): string | undefined {
  if (!colorValue) return undefined;

  const normalizedColor = colorValue.trim().toLowerCase();

  // 移除 # 号并转换 hex 颜色
  if (normalizedColor.startsWith('#')) {
    let hex = normalizedColor.substring(1);

    // 3位转6位
    if (hex.length === 3) {
      hex = hex.split('').map(c => c + c).join('');
    }

    if (hex.length === 6 && /^[0-9a-f]{6}$/i.test(hex)) {
      return hex.toUpperCase();
    }
  }

  // 解析 rgb/rgba
  const rgbMatch = normalizedColor.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*[\d.]+)?\s*\)/);
  if (rgbMatch) {
    const r = parseInt(rgbMatch[1], 10).toString(16).padStart(2, '0');
    const g = parseInt(rgbMatch[2], 10).toString(16).padStart(2, '0');
    const b = parseInt(rgbMatch[3], 10).toString(16).padStart(2, '0');
    return (r + g + b).toUpperCase();
  }

  // 常用颜色名称映射
  const colorNames: Record<string, string> = {
    black: '000000',
    white: 'FFFFFF',
    red: 'FF0000',
    green: '008000',
    blue: '0000FF',
    yellow: 'FFFF00',
    cyan: '00FFFF',
    magenta: 'FF00FF',
    orange: 'FFA500',
    purple: '800080',
    gray: '808080',
    grey: '808080',
    brown: 'A52A2A',
    pink: 'FFC0CB',
    navy: '000080',
    lime: '00FF00',
    maroon: '800000',
    teal: '008080',
    olive: '808000',
    silver: 'C0C0C0'
  };

  return colorNames[normalizedColor];
}

/**
 * 解析字体大小，支持 px、pt、em 等单位
 */
function parseFontSize(sizeValue: string): number | undefined {
  if (!sizeValue) return undefined;

  const normalizedSize = sizeValue.trim().toLowerCase();

  // 移除单位并获取数值
  const match = normalizedSize.match(/^(\d*\.?\d+)(px|pt|em|rem|%)?$/);
  if (!match) return undefined;

  const value = parseFloat(match[1]);
  const unit = match[2] || 'px';

  // 转换为半点（DOCX 使用半点作为单位）
  switch (unit) {
    case 'pt':
      return Math.round(value * 2); // 1pt = 2 半点
    case 'px':
      return Math.round(value * 1.5); // 1px ≈ 0.75pt ≈ 1.5 半点
    case 'em':
    case 'rem':
      return Math.round(value * 16 * 1.5); // 假设 1em = 16px
    case '%':
      return Math.round((value / 100) * 16 * 1.5); // 相对于 16px 基准
    default:
      return Math.round(value * 1.5);
  }
}

/**
 * 将像素高度转换为 DOCX 行高（twips）
 */
function convertHeightToLineHeight(heightPx: number): number {
  // 将像素转换为 twips（1px ≈ 15 twips）
  return Math.round(heightPx * 15);
}

/**
 * 解析 margin 值，支持 px、pt、em 等单位
 */
function parseMargin(marginValue: string): number | undefined {
  if (!marginValue) return undefined;

  const normalizedMargin = marginValue.trim().toLowerCase();

  const match = normalizedMargin.match(/^(\d*\.?\d+)(px|pt|em|rem|%)?$/);
  if (!match) return undefined;

  const value = parseFloat(match[1]);
  const unit = match[2] || 'px';

  // 转换为 twips（DOCX 使用 twips 作为间距单位，1pt = 20 twips）
  switch (unit) {
    case 'pt':
      return Math.round(value * 20); // 1pt = 20 twips
    case 'px':
      return Math.round(value * 15); // 1px ≈ 0.75pt ≈ 15 twips
    case 'em':
    case 'rem':
      return Math.round(value * 16 * 15); // 假设 1em = 16px
    default:
      return Math.round(value * 15); // 默认按 px 处理
  }
}

/**
 * 解析 margin 简写属性
 * 支持以下格式：
 * - margin: 10pt (所有方向)
 * - margin: 10pt 20pt (上下 左右)
 * - margin: 10pt 20pt 15pt (上 左右 下)
 * - margin: 10pt 20pt 15pt 25pt (上 右 下 左)
 */
function parseMarginShorthand(marginValue: string): {
  marginTop?: number;
  marginRight?: number;
  marginBottom?: number;
  marginLeft?: number;
} {
  if (!marginValue) return {};

  const parts = marginValue.trim().split(/\s+/);
  const result: {
    marginTop?: number;
    marginRight?: number;
    marginBottom?: number;
    marginLeft?: number;
  } = {};

  if (parts.length === 1) {
    // margin: 10pt
    const value = parseMargin(parts[0]);
    if (value !== undefined) {
      result.marginTop = value;
      result.marginRight = value;
      result.marginBottom = value;
      result.marginLeft = value;
    }
  } else if (parts.length === 2) {
    // margin: 10pt 20pt (上下 左右)
    const topBottom = parseMargin(parts[0]);
    const leftRight = parseMargin(parts[1]);
    if (topBottom !== undefined) {
      result.marginTop = topBottom;
      result.marginBottom = topBottom;
    }
    if (leftRight !== undefined) {
      result.marginLeft = leftRight;
      result.marginRight = leftRight;
    }
  } else if (parts.length === 3) {
    // margin: 10pt 20pt 15pt (上 左右 下)
    const top = parseMargin(parts[0]);
    const leftRight = parseMargin(parts[1]);
    const bottom = parseMargin(parts[2]);
    if (top !== undefined) result.marginTop = top;
    if (leftRight !== undefined) {
      result.marginLeft = leftRight;
      result.marginRight = leftRight;
    }
    if (bottom !== undefined) result.marginBottom = bottom;
  } else if (parts.length === 4) {
    // margin: 10pt 20pt 15pt 25pt (上 右 下 左)
    const top = parseMargin(parts[0]);
    const right = parseMargin(parts[1]);
    const bottom = parseMargin(parts[2]);
    const left = parseMargin(parts[3]);
    if (top !== undefined) result.marginTop = top;
    if (right !== undefined) result.marginRight = right;
    if (bottom !== undefined) result.marginBottom = bottom;
    if (left !== undefined) result.marginLeft = left;
  }

  return result;
}

/**
 * 解析缩进值，支持 px、pt、em 等单位
 */
function parseIndent(indentValue: string): number | undefined {
  if (!indentValue) return undefined;

  const normalizedIndent = indentValue.trim().toLowerCase();

  const match = normalizedIndent.match(/^(\d*\.?\d+)(px|pt|em|rem|%)?$/);
  if (!match) return undefined;

  const value = parseFloat(match[1]);
  const unit = match[2] || 'px';

  // 转换为 twips（DOCX 使用 twips 作为缩进单位，1pt = 20 twips）
  switch (unit) {
    case 'pt':
      return Math.round(value * 20);
    case 'px':
      return Math.round(value * 15); // 1px ≈ 0.75pt ≈ 15 twips
    case 'em':
    case 'rem':
      return Math.round(value * 16 * 15); // 假设 1em = 16px
    default:
      return Math.round(value * 15);
  }
}

/**
 * 解析边框宽度，支持 px、pt 等单位，转换为 twips
 */
function parseBorderWidth(widthValue: string): number | undefined {
  if (!widthValue) return undefined;

  const normalizedWidth = widthValue.trim().toLowerCase();

  // 处理常见关键字
  switch (normalizedWidth) {
    case 'thin':
      return 15; // 1px ≈ 15 twips
    case 'medium':
      return 30; // 2px ≈ 30 twips
    case 'thick':
      return 45; // 3px ≈ 45 twips
    case 'none':
    case '0':
      return 0;
    default:
      break;
  }

  const match = normalizedWidth.match(/^(\d*\.?\d+)(px|pt|em|rem)?$/);
  if (!match) return undefined;

  const value = parseFloat(match[1]);
  const unit = match[2] || 'px';

  if (Number.isNaN(value) || value < 0) return undefined;

  // 转换为 twips（1pt = 20 twips）
  switch (unit) {
    case 'pt':
      return Math.round(value * 20);
    case 'px':
      return Math.round(value * 15); // 1px ≈ 0.75pt ≈ 15 twips
    case 'em':
    case 'rem':
      return Math.round(value * 16 * 15); // 假设 1em = 16px
    default:
      return Math.round(value * 15); // 默认按px处理
  }
}

/**
 * 解析边框样式
 */
function parseBorderStyle(styleValue: string): 'single' | 'double' | 'dotted' | 'dashed' | 'none' | undefined {
  if (!styleValue) return undefined;

  const normalizedStyle = styleValue.trim().toLowerCase();

  switch (normalizedStyle) {
    case 'solid':
      return 'single';
    case 'double':
      return 'double';
    case 'dotted':
      return 'dotted';
    case 'dashed':
      return 'dashed';
    case 'none':
    case 'hidden':
      return 'none';
    default:
      return 'single'; // 默认为实线
  }
}

/**
 * 解析边框简写属性，如 "1px solid red" 或 "2pt dashed #333"
 * 特殊处理rgb颜色值，如 "1pt solid rgb(0, 0, 1)"
 */
function parseBorder(borderValue: string): ParsedBorderStyle | undefined {
  if (!borderValue || borderValue.trim().toLowerCase() === 'none') {
    return { style: 'none', width: 0 };
  }

  const border: ParsedBorderStyle = {};
  let remainingValue = borderValue.trim();

  // 尝试提取宽度
  const widthMatch = remainingValue.match(/^\s*(\d*\.?\d+\s*(?:px|pt|em|rem|thin|medium|thick))/i);
  if (widthMatch) {
    border.width = parseBorderWidth(widthMatch[1]);
    remainingValue = remainingValue.replace(widthMatch[0], '').trim();
  }

  // 尝试提取样式
  const styleMatch = remainingValue.match(/^\s*(solid|double|dotted|dashed|none)/i);
  if (styleMatch) {
    border.style = parseBorderStyle(styleMatch[1]);
    remainingValue = remainingValue.replace(styleMatch[0], '').trim();
  }

  // 尝试提取颜色
  // 处理rgb/rgba颜色值（可能包含逗号）
  const colorMatch = remainingValue.match(/^\s*(rgba?\(.*?\)|#[0-9a-f]{3,6}|[a-zA-Z]+)/i);
  if (colorMatch) {
    border.color = parseColor(colorMatch[1]);
  }

  // 设置默认值
  if (!border.width) border.width = 15; // 默认1px
  if (!border.style) border.style = 'single'; // 默认实线
  if (!border.color) border.color = '000000'; // 默认黑色

  return border;
}

/**
 * 解析缩放值，支持百分比 - 用于字符间距缩放
 */
function parseScale(scaleValue: string): number | undefined {
  if (!scaleValue) return undefined;

  const normalizedScale = scaleValue.trim();

  // 移除 % 号并获取数值
  const value = parseFloat(normalizedScale.replace('%', ''));

  if (Number.isNaN(value) || value <= 0) return undefined;

  // 返回缩放比例 (例如：55% 返回 55)
  return value;
}

/**
 * 解析文本对齐值
 */
function parseTextAlign(alignValue: string): 'left' | 'center' | 'right' | 'justify' | undefined {
  if (!alignValue) return undefined;

  const normalizedAlign = alignValue.trim().toLowerCase();

  switch (normalizedAlign) {
    case 'left':
      return 'left';
    case 'center':
      return 'center';
    case 'right':
      return 'right';
    case 'justify':
      return 'justify';
    default:
      return undefined;
  }
}

/**
 * 将文本对齐值转换为 DOCX AlignmentType
 */
function convertToAlignmentType(align: 'left' | 'center' | 'right' | 'justify' | undefined): typeof AlignmentType[keyof typeof AlignmentType] | undefined {
  if (!align) return undefined;

  switch (align) {
    case 'left':
      return AlignmentType.LEFT;
    case 'center':
      return AlignmentType.CENTER;
    case 'right':
      return AlignmentType.RIGHT;
    case 'justify':
      return AlignmentType.JUSTIFIED;
    default:
      return undefined;
  }
}

/**
 * 将ParsedBorderStyle转换为DOCX BorderStyle
 */
function convertToDOCXBorderStyle(border?: ParsedBorderStyle): any {
  // 确保即使是默认边框也有样式
  if (!border) {
    return undefined;
  }

  // 只有明确指定为none的边框才返回无边框样式
  if (border.style === 'none' || border.width === 0) {
    return undefined;
  }

  let docxStyle: any = BorderStyle.SINGLE;
  const styleType = border.style as string;
  if (styleType) {
    switch (styleType) {
      case 'single':
        docxStyle = BorderStyle.SINGLE;
        break;
      case 'double':
        docxStyle = BorderStyle.DOUBLE;
        break;
      case 'dotted':
        docxStyle = BorderStyle.DOTTED;
        break;
      case 'dashed':
        docxStyle = BorderStyle.DASHED;
        break;
      case 'none':
        return undefined;
      default:
        docxStyle = BorderStyle.SINGLE;
        break;
    }
  }

  return {
    style: docxStyle,
    size: Math.max(1, Math.round((border.width || 15) / 8)), // 转换twips为eighth-points
    color: border.color || '000000'
  };
}

/**
 * 转换行高设置为DOCX spacing属性
 */
function convertToSpacing(lineHeight?: { line: number; lineRule: string }): any {
  if (!lineHeight) return undefined;

  if (lineHeight.lineRule === 'auto') {
    // 倍数行距或自动行距
    return { line: lineHeight.line, lineRule: 'auto' };
  }
  if (lineHeight.lineRule === 'atLeast') {
    // 最小行距：确保行高不小于指定值
    return { line: lineHeight.line, lineRule: 'atLeast' };
  }
  // 固定行距
  return { line: lineHeight.line, lineRule: 'exact' };
}

/**
 * 解析行高值，返回包含值和规则的对象
 * @param lineHeightValue 行高值字符串
 * @param baseFontSize 基础字体大小（半点单位，来自 parseFontSize）
 */
function parseLineHeight(
  lineHeightValue: string,
  baseFontSize: number = 24
): { line: number; lineRule: string } | undefined {
  if (!lineHeightValue) return undefined;

  const normalizedLineHeight = lineHeightValue.trim().toLowerCase();

  // 将基础字体大小从半点转换为点
  const baseFontSizeInPt = baseFontSize / 2;

  // 处理 normal 关键字 - 使用自动行距
  if (normalizedLineHeight === 'normal') {
    return {
      line: Math.round(baseFontSizeInPt * 1.2 * 20), // 1.2倍行高转换为twips
      lineRule: 'auto'
    };
  }

  // 纯数字（倍数行距）
  const numberMatch = normalizedLineHeight.match(/^(\d*\.?\d+)$/);
  if (numberMatch) {
    const multiplier = parseFloat(numberMatch[1]);
    if (!Number.isNaN(multiplier) && multiplier > 0) {
      // 倍数行距：使用相对于字体大小的倍数
      return {
        line: Math.round(240 * multiplier), // DOCX中倍数行距使用240为基数
        lineRule: 'auto'
      };
    }
  }

  // 带单位的值（固定行距）
  const unitMatch = normalizedLineHeight.match(/^(\d*\.?\d+)(px|pt|em|rem|%)?$/);
  if (!unitMatch) return undefined;

  const value = parseFloat(unitMatch[1]);
  const unit = unitMatch[2] || 'px';

  if (Number.isNaN(value) || value <= 0) return undefined;

  // 固定行距：转换为 twips（1pt = 20 twips）
  let lineValue: number;
  switch (unit) {
    case 'pt':
      lineValue = Math.round(value * 20); // 1pt = 20 twips
      break;
    case 'px':
      lineValue = Math.round(value * 15); // 1px ≈ 0.75pt ≈ 15 twips
      break;
    case 'em':
    case 'rem':
      // 基于基础字体大小
      lineValue = Math.round(baseFontSizeInPt * value * 20);
      break;
    case '%': {
      // 百分比转换为倍数行距
      const multiplier = value / 100;
      return {
        line: Math.round(240 * multiplier),
        lineRule: 'auto'
      };
    }
    default:
      lineValue = Math.round(value * 15); // 默认按px处理
      break;
  }

  return {
    line: lineValue,
    lineRule: 'exact' // 固定行距
  };
}

/**
 * 使用JSDOM获取元素的计算样式
 */
/**
 * 解析元素的内联样式和自定义属性，同时应用CSS规则和计算样式
 */
function parseInlineStyle(
  element: Element,
  cssRules?: CSSRuleSet,
  parentElement?: Element
): ParsedStyle {
  const style: ParsedStyle = {};
  const styleAttr = element.getAttribute('style');

  // 0. 如果有父元素，先继承父元素的样式
  if (parentElement) {
    const parentStyle = parseInlineStyle(parentElement, cssRules);
    // 继承可继承的属性
    if (parentStyle.color) style.color = parentStyle.color;
    if (parentStyle.fontSize) style.fontSize = parentStyle.fontSize;
    if (parentStyle.fontFamily) style.fontFamily = parentStyle.fontFamily;
    if (parentStyle.bold !== undefined) style.bold = parentStyle.bold;
    if (parentStyle.italic !== undefined) style.italic = parentStyle.italic;
    if (parentStyle.underline !== undefined) style.underline = parentStyle.underline;
    if (parentStyle.textAlign) style.textAlign = parentStyle.textAlign;
    if (parentStyle.lineHeight) style.lineHeight = parentStyle.lineHeight;
    if (parentStyle.characterSpacing !== undefined) {
      style.characterSpacing = parentStyle.characterSpacing;
    }
  }

  // 解析 data-scale 自定义属性 - 用于字符间距缩放
  const dataScale = element.getAttribute('data-scale');
  if (dataScale) {
    console.log('找到 data-scale:', dataScale, '在元素:', element.tagName);
    style.characterSpacing = parseScale(dataScale);
  }

  // 1. 应用来自style标签的CSS规则（如果有）
  if (cssRules) {
    // 获取元素的选择器路径
    const tagName = element.tagName?.toLowerCase() || '';
    const id = element.getAttribute('id');
    const classList = element.getAttribute('class')?.split(/\s+/).filter((cls: string) => cls.trim()) || [];

    // 检查并应用匹配的CSS规则
    Object.keys(cssRules).forEach(selector => {
      let isMatch = false;

      // 标签选择器匹配
      if (selector === tagName) {
        isMatch = true;
      } else if (selector.startsWith('#') && id && selector === `#${id}`) {
        // ID选择器匹配
        isMatch = true;
      } else if (selector.startsWith('.') && classList.some(cls => selector === `.${cls}`)) {
        // 类选择器匹配
        isMatch = true;
      } else if (selector.includes('#')) {
        // 组合选择器匹配（简单版本）
        const selectorId = selector.match(/#([^.\s]+)/)?.[1];
        if (selectorId && id === selectorId) {
          isMatch = true;
        }
      } else if (selector.includes('.')) {
        const selectorClass = selector.match(/\.([^#\s]+)/)?.[1];
        if (selectorClass && classList.includes(selectorClass)) {
          isMatch = true;
        }
      }

      if (isMatch) {
        const ruleProperties = cssRules[selector];
        Object.keys(ruleProperties).forEach(property => {
          const value = ruleProperties[property];

          // 应用CSS规则属性
          switch (property.toLowerCase()) {
            case 'color':
              if (!style.color) {
                style.color = parseColor(value);
              }
              break;
            case 'font-size':
              if (!style.fontSize) {
                style.fontSize = parseFontSize(value);
              }
              break;
            case 'font-family':
              if (!style.fontFamily) {
                style.fontFamily = value.replace(/['"]/g, '').split(',')[0].trim();
              }
              break;
            case 'font-weight':
              if (style.bold === undefined) {
                style.bold = value === 'bold' || value === 'bolder' || parseInt(value, 10) >= 600;
              }
              break;
            case 'font-style':
              if (style.italic === undefined) {
                style.italic = value === 'italic' || value === 'oblique';
              }
              break;
            case 'text-decoration':
              if (style.underline === undefined) {
                style.underline = value.includes('underline');
              }
              if (style.strikethrough === undefined) {
                style.strikethrough = value.includes('line-through');
              }
              break;
            case 'text-indent':
            case 'padding-left':
              if (!style.indent) { // 只取第一个有效的缩进值
                style.indent = parseIndent(value);
              }
              break;
            case 'text-align':
              if (!style.textAlign) {
                style.textAlign = parseTextAlign(value);
              }
              break;
            case 'line-height':
              // 需要传入当前字体大小作为基准，如果没有则使用默认值
              if (!style.lineHeight) {
                style.lineHeight = parseLineHeight(value, style.fontSize || 24);
              }
              break;
            case 'background-color':
              if (!style.backgroundColor) {
                style.backgroundColor = parseColor(value);
              }
              break;
            case 'border':
              if (!style.border) {
                style.border = parseBorder(value);
              }
              break;
            case 'border-top':
              if (!style.borderTop) {
                style.borderTop = parseBorder(value);
              }
              break;
            case 'border-right':
              if (!style.borderRight) {
                style.borderRight = parseBorder(value);
              }
              break;
            case 'border-bottom':
              if (!style.borderBottom) {
                style.borderBottom = parseBorder(value);
              }
              break;
            case 'border-left':
              if (!style.borderLeft) {
                style.borderLeft = parseBorder(value);
              }
              break;
            case 'margin-bottom':
              if (!style.marginBottom) {
                style.marginBottom = parseMargin(value);
              }
              break;
            case 'margin-top':
              if (!style.marginTop) {
                style.marginTop = parseMargin(value);
              }
              break;
            case 'margin-right':
              if (!style.marginRight) {
                style.marginRight = parseMargin(value);
              }
              break;
            case 'margin-left':
              if (!style.marginLeft) {
                style.marginLeft = parseMargin(value);
              }
              break;

            // 可以添加更多的属性处理...
            default:
              break;
          }
        });
      }
    });
  }

  // 2. 解析内联样式（优先级高于CSS规则）
  if (styleAttr) {
    const inlineRules = styleAttr.split(';').map(rule => rule.trim()).filter(rule => rule);

    inlineRules.forEach(rule => {
      const [property, value] = rule.split(':').map(s => s.trim());
      if (!property || !value) return;

      switch (property.toLowerCase()) {
        case 'color':
          style.color = parseColor(value);
          break;
        case 'font-size':
          style.fontSize = parseFontSize(value);
          break;
        case 'font-family':
          style.fontFamily = value.replace(/['"]/g, '').split(',')[0].trim();
          break;
        case 'font-weight':
          style.bold = value === 'bold' || value === 'bolder' || parseInt(value, 10) >= 600;
          break;
        case 'font-style':
          style.italic = value === 'italic' || value === 'oblique';
          break;
        case 'text-decoration':
          style.underline = value.includes('underline');
          style.strikethrough = value.includes('line-through');
          break;
        case 'text-indent':
        case 'padding-left':
          if (!style.indent) { // 只取第一个有效的缩进值
            style.indent = parseIndent(value);
          }
          break;
        case 'margin-top':
          style.marginTop = parseMargin(value);
          break;
        case 'margin-right':
          style.marginRight = parseMargin(value);
          break;
        case 'margin-bottom':
          style.marginBottom = parseMargin(value);
          break;
        case 'margin-left':
          style.marginLeft = parseMargin(value);
          break;
        case 'margin': {
          // 处理 margin 简写属性
          const marginShorthand = parseMarginShorthand(value);
          if (marginShorthand.marginTop !== undefined) {
            style.marginTop = marginShorthand.marginTop;
          }
          if (marginShorthand.marginRight !== undefined) {
            style.marginRight = marginShorthand.marginRight;
          }
          if (marginShorthand.marginBottom !== undefined) {
            style.marginBottom = marginShorthand.marginBottom;
          }
          if (marginShorthand.marginLeft !== undefined) {
            style.marginLeft = marginShorthand.marginLeft;
          }
          break;
        }
        case 'text-align':
          style.textAlign = parseTextAlign(value);
          break;
        case 'line-height':
          // 需要传入当前字体大小作为基准，如果没有则使用默认值
          style.lineHeight = parseLineHeight(value, style.fontSize || 24);
          break;
        case 'background-color':
          style.backgroundColor = parseColor(value);
          break;
        case 'border':
          style.border = parseBorder(value);
          break;
        case 'border-top':
          style.borderTop = parseBorder(value);
          break;
        case 'border-right':
          style.borderRight = parseBorder(value);
          break;
        case 'border-bottom':
          style.borderBottom = parseBorder(value);
          break;
        case 'border-left':
          style.borderLeft = parseBorder(value);
          break;
        case 'border-width':
          // 处理单独的宽度设置
          if (!style.border) style.border = {};
          style.border.width = parseBorderWidth(value);
          break;
        case 'border-style':
          // 处理单独的样式设置
          if (!style.border) style.border = {};
          style.border.style = parseBorderStyle(value);
          break;
        case 'border-color':
          // 处理单独的颜色设置
          if (!style.border) style.border = {};
          style.border.color = parseColor(value);
          break;
        default:
          // 忽略不支持的样式属性
          break;
      }
    });
  }

  // 3. 在没有获取到关键样式属性时，尝试使用浏览器原生的getComputedStyle获取计算样式（样式继承）
  // 只在浏览器环境中并且缺少某些关键样式属性时才使用
  if (typeof window !== 'undefined' && (!style.color || !style.fontSize || !style.fontFamily)) {
    try {
      // 注意：在实际的浏览器环境中，我们可以直接使用DOM元素的getComputedStyle
      // 这里我们只是返回一个空对象，因为在实际使用时，cheerio元素没有直接对应的DOM元素
      // 在实际集成到浏览器环境的代码中，应该传入真实的DOM元素而不是cheerio元素
      return style;
    } catch (error) {
      console.warn('获取计算样式失败:', error);
    }
  }

  return style;
}

/**
 * 合并多个样式对象
 */
function mergeStyles(...styles: ParsedStyle[]): ParsedStyle {
  const merged: ParsedStyle = {};

  styles.forEach(style => {
    if (style.color) merged.color = style.color;
    if (style.fontSize) merged.fontSize = style.fontSize;
    if (style.fontFamily) merged.fontFamily = style.fontFamily;
    if (style.bold !== undefined) merged.bold = style.bold;
    if (style.italic !== undefined) merged.italic = style.italic;
    if (style.underline !== undefined) merged.underline = style.underline;
    if (style.strikethrough !== undefined) merged.strikethrough = style.strikethrough;
    if (style.indent !== undefined) merged.indent = style.indent;
    if (style.characterSpacing !== undefined) merged.characterSpacing = style.characterSpacing;
    if (style.textAlign) merged.textAlign = style.textAlign;
    if (style.lineHeight) merged.lineHeight = style.lineHeight;
    if (style.backgroundColor) merged.backgroundColor = style.backgroundColor;
    if (style.border) merged.border = style.border;
    if (style.borderTop) merged.borderTop = style.borderTop;
    if (style.borderRight) merged.borderRight = style.borderRight;
    if (style.borderBottom) merged.borderBottom = style.borderBottom;
    if (style.borderLeft) merged.borderLeft = style.borderLeft;
    if (style.marginTop !== undefined) merged.marginTop = style.marginTop;
    if (style.marginRight !== undefined) merged.marginRight = style.marginRight;
    if (style.marginBottom !== undefined) merged.marginBottom = style.marginBottom;
    if (style.marginLeft !== undefined) merged.marginLeft = style.marginLeft;
    if (style.href) merged.href = style.href;
  });

  return merged;
}

/**
 * 计算最终的字体大小 - 简化版本，不再处理缩放
 */
function calculateFinalFontSize(
  currentFontSize: number | undefined,
  parentFontSize: number | undefined
): number | undefined {
  return currentFontSize || parentFontSize;
}

/**
 * 计算字符缩放值，用于 DOCX 的 scale 属性
 */
function calculateCharacterScale(scale: number | undefined): number | undefined {
  if (scale === undefined) return undefined;

  // DOCX 中 scale 属性的单位是百分比
  // 直接返回百分比值，例如 55% -> 55
  return Math.round(scale);
}

/**
 * 从 URL 或 base64 字符串获取图片数据
 */
async function getImageData(src: string): Promise<ImageInfo | null> {
  try {
    if (src.startsWith('data:')) {
      // 处理 base64 图片
      const base64Data = src.split(',')[1];
      const mimeType = src.split(',')[0].split(':')[1].split(';')[0];

      if (isBrowser()) {
        // 浏览器环境
        const response = await fetch(src);
        const blob = await response.blob();
        const arrayBuffer = await blob.arrayBuffer();
        const data = new Uint8Array(arrayBuffer);

        // 创建临时 Image 元素获取尺寸
        return new Promise((resolve) => {
          const img = new Image();
          img.onload = () => {
            resolve({
              data,
              width: img.width,
              height: img.height,
              type: mimeType
            });
          };
          img.onerror = () => resolve(null);
          img.src = src;
        });
      }

      // Node.js 环境
      const data = Buffer.from(base64Data, 'base64');

      // 尝试解析图片尺寸
      let width = 400;
      let height = 300;

      try {
        if (mimeType === 'image/png') {
          // PNG 文件头包含尺寸信息
          if (data.length >= 24) {
            width = data.readUInt32BE(16);
            height = data.readUInt32BE(20);
          }
        } else if (mimeType === 'image/jpeg') {
          // JPEG 文件需要更复杂的解析，这里使用简单的方法
          let i = 0;
          while (i < data.length - 2) {
            if (data[i] === 0xFF && data[i + 1] === 0xC0) {
              // SOF0 标记
              if (i + 9 < data.length) {
                height = data.readUInt16BE(i + 5);
                width = data.readUInt16BE(i + 7);
                break;
              }
            }
            i += 1;
          }
        } else if (mimeType === 'image/gif') {
          // GIF 文件头包含尺寸信息
          if (data.length >= 10) {
            width = data.readUInt16LE(6);
            height = data.readUInt16LE(8);
          }
        }
      } catch (error) {
        console.warn('解析图片尺寸失败，使用默认尺寸:', error);
      }

      return {
        data,
        width,
        height,
        type: mimeType
      };
    }

    // 处理 blob URL
    if (src.startsWith('blob:')) {
      if (isBrowser()) {
        // 浏览器环境：使用 fetch 处理 blob URL
        const response = await fetch(src);
        if (!response.ok) throw new Error(`无法获取 blob 数据: HTTP ${response.status}`);

        const blob = await response.blob();
        const arrayBuffer = await blob.arrayBuffer();
        const data = new Uint8Array(arrayBuffer);

        // 创建临时 Image 元素获取尺寸
        return new Promise((resolve) => {
          const img = new Image();
          img.onload = () => {
            resolve({
              data,
              width: img.width,
              height: img.height,
              type: blob.type || 'image/jpeg'
            });
          };
          img.onerror = () => resolve(null);
          img.src = src;
        });
      }

      // Node.js 环境不支持 blob URL
      throw new Error('Node.js 环境下不支持 blob: URL，请将图片转换为 base64 格式');
    }

    // 处理远程图片 URL (http/https)
    if (src.startsWith('http://') || src.startsWith('https://')) {
      if (isBrowser()) {
        // 浏览器环境：使用 fetch
        const response = await fetch(src);
        if (!response.ok) throw new Error(`HTTP ${response.status}`);

        const blob = await response.blob();
        const arrayBuffer = await blob.arrayBuffer();
        const data = new Uint8Array(arrayBuffer);

        // 创建临时 Image 元素获取尺寸
        return new Promise((resolve) => {
          const img = new Image();
          img.onload = () => {
            resolve({
              data,
              width: img.width,
              height: img.height,
              type: blob.type || 'image/jpeg'
            });
          };
          img.onerror = () => resolve(null);
          img.src = src;
        });
      }

      // Node.js 环境：仅支持 base64，远程图片需要用户预处理
      throw new Error('Node.js 环境下仅支持 base64 图片，远程图片请先转换为 base64');
    }

    // 其他格式的 URL 或路径
    throw new Error(`不支持的图片格式或路径: ${src}`);
  } catch (error: any) {
    console.warn('Failed to load image:', src, error);
    return null;
  }
}

/**
 * 计算 Word 文档的书写区域宽度（以像素为单位）
 * A4 纸宽度：21cm = 595.28pt ≈ 794px
 * 默认左右边距：2.54cm = 72pt ≈ 96px
 * 书写区域宽度：794 - 96*2 = 602px
 */
function calculateWordPageWidth(options: HtmlToDocxOptions = {}): number {
  // A4 纸宽度：21cm
  const a4WidthCm = 21;

  // 获取左右边距（厘米）
  const leftMarginCm = options.margins?.left || 2.54;
  const rightMarginCm = options.margins?.right || 2.54;

  // 计算内容区域宽度（厘米）
  const contentWidthCm = a4WidthCm - leftMarginCm - rightMarginCm;

  // 将厘米转换为像素（1cm ≈ 37.8px）
  const contentWidthPx = Math.round(contentWidthCm * 37.8);

  return Math.max(100, contentWidthPx); // 确保最小宽度
}

/**
 * 计算图片的显示尺寸
 */
function calculateImageSize(
  originalWidth: number,
  originalHeight: number,
  maxWidth: number = 600,
  maxHeight: number = 400,
  applyMinHeight: boolean = true
): { width: number; height: number } {
  const aspectRatio = originalWidth / originalHeight;

  let width = originalWidth;
  let height = originalHeight;

  // 限制最大宽度
  if (width > maxWidth) {
    width = maxWidth;
    height = width / aspectRatio;
  }

  // 限制最大高度，但不要过度限制
  if (height > maxHeight) {
    height = maxHeight;
    width = height * aspectRatio;
  }

  // 确保最小高度（至少 10 像素），但不要超出最大宽度
  // 只有在需要应用最小高度限制时才执行
  if (applyMinHeight && height < 10) {
    // 尝试设置最小高度
    const minHeight = 10;
    const calculatedWidth = minHeight * aspectRatio;

    if (calculatedWidth <= maxWidth) {
      // 如果计算出的宽度不超出最大宽度，使用最小高度
      height = minHeight;
      width = calculatedWidth;
    } else {
      // 如果会超出最大宽度，则使用最大宽度，但确保最小高度
      width = maxWidth;
      height = width / aspectRatio;

      // 如果高度仍然太小，强制设置一个最小高度
      if (height < 10) {
        height = 10;
      }
    }
  }

  return { width: Math.round(width), height: Math.round(height) };
}

/**
 * 创建图片段落
 */
async function createImageParagraph(
  element: Element,
  cssRules?: CSSRuleSet,
  options: HtmlToDocxOptions = {}
): Promise<{ paragraph: Paragraph | null; warnings: string[] }> {
  const warnings: string[] = [];
  const src = element.getAttribute('src');

  if (!src) {
    warnings.push('图片标签缺少 src 属性');
    return { paragraph: null, warnings };
  }

  try {
    const imageInfo = await getImageData(src);
    if (!imageInfo) {
      warnings.push(`无法加载图片: ${src}`);
      return { paragraph: null, warnings };
    }

    // 解析图片样式，传入undefined作为父元素
    const style = parseInlineStyle(element, cssRules);

    // 解析 HTML 中的尺寸属性
    let displayWidth = imageInfo.width;
    let displayHeight = imageInfo.height;

    // 检查 HTML 属性
    const htmlWidth = element.getAttribute('width');
    const htmlHeight = element.getAttribute('height');

    // 检查 CSS 样式
    const styleAttr = element.getAttribute('style');
    let cssWidth: string | undefined;
    let cssHeight: string | undefined;
    let cssMarginBottom: string | undefined;

    if (styleAttr) {
      const styleRules = styleAttr.split(';').map(rule => rule.trim()).filter(rule => rule);
      styleRules.forEach(rule => {
        const [property, value] = rule.split(':').map(s => s.trim());
        if (property === 'width') cssWidth = value;
        if (property === 'height') cssHeight = value;
        if (property === 'margin-bottom') cssMarginBottom = value;
      });
    }

    // 优先使用 CSS 样式，然后是 HTML 属性
    if (cssHeight) {
      const heightMatch = cssHeight.match(/^(\d+)px$/);
      if (heightMatch) {
        displayHeight = parseInt(heightMatch[1], 10);
        // 保持宽高比
        displayWidth = Math.round((displayHeight / imageInfo.height) * imageInfo.width);
      }
    } else if (htmlHeight) {
      displayHeight = parseInt(htmlHeight, 10);
      displayWidth = Math.round((displayHeight / imageInfo.height) * imageInfo.width);
    }

    if (cssWidth) {
      if (cssWidth === '100%') {
        // 100% 宽度，使用 Word 页面宽度
        displayWidth = calculateWordPageWidth(options);
        if (!cssHeight && !htmlHeight) {
          // 只有在没有设置高度的情况下才重新计算高度
          displayHeight = Math.round((displayWidth / imageInfo.width) * imageInfo.height);
        }
      } else {
        const widthMatch = cssWidth.match(/^(\d+)px$/);
        if (widthMatch) {
          displayWidth = parseInt(widthMatch[1], 10);
          // 只有在没有设置高度的情况下才重新计算高度
          if (!cssHeight && !htmlHeight) {
            displayHeight = Math.round((displayWidth / imageInfo.width) * imageInfo.height);
          }
        }
      }
    } else if (htmlWidth) {
      if (htmlWidth === '100%') {
        displayWidth = calculateWordPageWidth(options);
        if (!cssHeight && !htmlHeight) {
          displayHeight = Math.round((displayWidth / imageInfo.width) * imageInfo.height);
        }
      } else {
        displayWidth = parseInt(htmlWidth, 10);
        if (!cssHeight && !htmlHeight) {
          displayHeight = Math.round((displayWidth / imageInfo.width) * imageInfo.height);
        }
      }
    }

    // 应用最大尺寸限制
    const pageWidth = calculateWordPageWidth(options);

    // 检查用户是否明确设置了高度
    const hasExplicitHeight = cssHeight || htmlHeight;

    // 检查是否为 100% 宽度
    const is100PercentWidth = (cssWidth === '100%') || (htmlWidth === '100%');

    // 检查用户是否明确设置了宽度
    const hasExplicitWidth = (cssWidth && cssWidth !== '100%') || (htmlWidth && htmlWidth !== '100%');

    let width; let
      height;
    if (is100PercentWidth) {
      // 100% 宽度：直接使用计算出的尺寸，不应用最大限制
      width = displayWidth;
      height = displayHeight;
    } else if (hasExplicitWidth) {
      // 用户明确设置了宽度：直接使用计算出的尺寸，但确保最小高度为1像素
      width = displayWidth;
      height = Math.max(displayHeight, 1); // 确保最小高度为1像素
    } else {
      // 其他情况：应用最大尺寸限制
      const result = calculateImageSize(
        displayWidth,
        displayHeight,
        Math.min(options.maxImageWidth || pageWidth, pageWidth),
        options.maxImageHeight || 400,
        !hasExplicitHeight // 只有在没有明确设置高度时才应用最小高度限制
      );
      width = result.width;
      height = result.height;
    }
    // 创建图片运行
    const imageRun = new ImageRun({
      data: imageInfo.data,
      transformation: {
        width,
        height
      },
      type: imageInfo.type.includes('png') ? 'png' : 'jpg'
    });

    // 解析 margin-bottom
    const marginBottom = cssMarginBottom ? parseMargin(cssMarginBottom) : undefined;

    // 设置行高为图片高度加上 margin，同时 margin 也作为段落间距
    const imageLineHeight = convertHeightToLineHeight(height);
    const totalLineHeight = marginBottom ? imageLineHeight + marginBottom : imageLineHeight;

    const paragraph = new Paragraph({
      children: [imageRun],
      indent: style.indent ? { left: style.indent } : undefined,
      spacing: {
        line: totalLineHeight,
        lineRule: 'exact',
        ...(marginBottom ? { after: marginBottom } : {})
      }
    });

    return { paragraph, warnings };
  } catch (error: any) {
    warnings.push(`图片处理失败: ${src} - ${error.message}`);
    return { paragraph: null, warnings };
  }
}

/**
 * 创建标题段落
 */
function createHeading(
  element: Element,
  tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6',
  cssRules?: CSSRuleSet
): Paragraph {
  const headingLevels = {
    h1: HeadingLevel.HEADING_1,
    h2: HeadingLevel.HEADING_2,
    h3: HeadingLevel.HEADING_3,
    h4: HeadingLevel.HEADING_4,
    h5: HeadingLevel.HEADING_5,
    h6: HeadingLevel.HEADING_6
  };

  // 解析样式，传入undefined作为父元素（因为这是顶级元素）
  const inlineStyle = parseInlineStyle(element, cssRules);

  // 创建文本运行
  const textRun = new TextRun({
    text: element.textContent || '',
    color: inlineStyle.color,
    size: inlineStyle.fontSize,
    font: inlineStyle.fontFamily,
    bold: inlineStyle.bold,
    italics: inlineStyle.italic,
    underline: inlineStyle.underline ? {} : undefined,
    strike: inlineStyle.strikethrough || undefined,
    scale: calculateCharacterScale(inlineStyle.characterSpacing)
  });

  // 处理缩进：优先使用 margin-left/right，然后是 indent
  const indentObj: any = {};
  if (inlineStyle.marginLeft !== undefined) {
    indentObj.left = inlineStyle.marginLeft;
  } else if (inlineStyle.indent !== undefined) {
    indentObj.left = inlineStyle.indent;
  }

  if (inlineStyle.marginRight !== undefined) {
    indentObj.right = inlineStyle.marginRight;
  }

  return new Paragraph({
    heading: headingLevels[tag],
    children: [textRun],
    indent: Object.keys(indentObj).length > 0 ? indentObj : undefined,
    alignment: convertToAlignmentType(inlineStyle.textAlign),
    spacing: {
      ...convertToSpacing(inlineStyle.lineHeight),
      ...(inlineStyle.marginTop ? { before: inlineStyle.marginTop } : {}),
      ...(inlineStyle.marginBottom ? { after: inlineStyle.marginBottom } : {})
    }
  });
}

/**
 * 解析文本内容，包括格式化和样式，同时收集最大字体大小
 */
function parseTextContent(
  element: Element,
  cssRules?: CSSRuleSet,
  parentStyle: ParsedStyle = {}
): { textRuns: any[], maxFontSize: number | undefined } {
  const textRuns: any[] = [];
  let maxFontSize: number | undefined = parentStyle.fontSize;

  // 遍历所有子节点
  for (let i = 0; i < element.childNodes.length; i++) {
    const node = element.childNodes[i];
    if (node.nodeType === 3) { // 文本节点
      const text = node.textContent || '';
      // 不要使用 trim() 来检查，因为空格也是有效内容
      if (text.length > 0) {
        textRuns.push(new TextRun({
          text,
          color: parentStyle.color,
          size: parentStyle.fontSize,
          font: parentStyle.fontFamily,
          bold: parentStyle.bold,
          italics: parentStyle.italic,
          underline: parentStyle.underline ? {} : undefined,
          strike: parentStyle.strikethrough || undefined,
          scale: calculateCharacterScale(parentStyle.characterSpacing)
        }));
      }
    } else if (node.nodeType === 1) { // 元素节点
      const elementNode = node as Element;
      const tagName = elementNode.tagName?.toLowerCase();
      const text = elementNode.textContent || '';

      if (!text.trim()) continue;

      // 解析内联样式，传入父元素以支持样式继承
      const inlineStyle = parseInlineStyle(elementNode, cssRules, element);

      // 基于标签的默认样式
      const tagStyle: ParsedStyle = {};
      switch (tagName) {
        case 'b':
        case 'strong':
          tagStyle.bold = true;
          break;
        case 'i':
        case 'em':
          tagStyle.italic = true;
          break;
        case 'u':
          tagStyle.underline = true;
          break;
        case 'a': {
          tagStyle.color = '0000FF';
          tagStyle.underline = true;
          // 获取 href 属性用于超链接
          const href = elementNode.getAttribute('href') || undefined;
          if (href) {
            tagStyle.href = href;
          }
          break;
        }
        case 'small':
          tagStyle.fontSize = Math.round((parentStyle.fontSize || 24) * 0.8);
          break;
        case 'big':
          tagStyle.fontSize = Math.round((parentStyle.fontSize || 24) * 1.2);
          break;
        case 'sub':
          tagStyle.fontSize = Math.round((parentStyle.fontSize || 24) * 0.7);
          break;
        case 'sup':
          tagStyle.fontSize = Math.round((parentStyle.fontSize || 24) * 0.7);
          break;
        default:
          // 没有特殊样式的标签
          break;
      }

      // 合并样式：父级样式 < 标签默认样式 < 内联样式
      const finalStyle = mergeStyles(parentStyle, tagStyle, inlineStyle);

      // 计算最终的字体大小
      finalStyle.fontSize = calculateFinalFontSize(finalStyle.fontSize, parentStyle.fontSize);

      // 更新最大字体大小
      if (finalStyle.fontSize && (!maxFontSize || finalStyle.fontSize > maxFontSize)) {
        maxFontSize = finalStyle.fontSize;
      }

      // 检查是否包含子元素
      if (elementNode.children.length > 0) {
        // 递归解析子元素
        const {
          textRuns: childTextRuns,
          maxFontSize: childMaxFontSize
        } = parseTextContent(elementNode, cssRules, finalStyle);
        textRuns.push(...childTextRuns);

        // 更新最大字体大小
        if (childMaxFontSize && (!maxFontSize || childMaxFontSize > maxFontSize)) {
          maxFontSize = childMaxFontSize;
        }
      } else {
        // 创建文本运行
        const calculatedScale = calculateCharacterScale(finalStyle.characterSpacing);

        // 如果有超链接，创建超链接
        if (finalStyle.href) {
          const hyperlink = new ExternalHyperlink({
            link: finalStyle.href,
            children: [
              new TextRun({
                text,
                color: finalStyle.color,
                size: finalStyle.fontSize,
                font: finalStyle.fontFamily,
                bold: finalStyle.bold,
                italics: finalStyle.italic,
                underline: finalStyle.underline ? {} : undefined,
                strike: finalStyle.strikethrough || undefined,
                scale: calculatedScale
              })
            ]
          });
          textRuns.push(hyperlink);
        } else {
          // 普通文本运行
          const textRun = new TextRun({
            text,
            color: finalStyle.color,
            size: finalStyle.fontSize,
            font: finalStyle.fontFamily,
            bold: finalStyle.bold,
            italics: finalStyle.italic,
            underline: finalStyle.underline ? {} : undefined,
            strike: finalStyle.strikethrough || undefined,
            scale: calculatedScale
          });
          textRuns.push(textRun);
        }
      }
    }
  }

  return { textRuns, maxFontSize };
}

/**
 * 创建普通段落
 */
function createParagraph(
  element: Element,
  cssRules?: CSSRuleSet,
  bodyStyle?: ParsedStyle
): Paragraph {
  // 解析段落级别的样式，传入undefined作为父元素（因为这是顶级元素）
  const paragraphStyle = parseInlineStyle(element, cssRules);

  // 如果有bodyStyle，将其与段落样式合并
  const finalParagraphStyle = bodyStyle ? mergeStyles(bodyStyle, paragraphStyle) : paragraphStyle;

  // 检查是否包含图片
  const hasImages = element.querySelectorAll('img').length > 0;

  if (hasImages) {
    // 如果包含图片，暂时跳过，因为需要异步处理
    console.warn('检测到图片标签，但段落暂不支持图片');
    // 返回一个空段落，图片将由 parseElement 单独处理
    return new Paragraph({
      children: [new TextRun('')]
    });
  }

  const { textRuns, maxFontSize } = parseTextContent(element, cssRules, finalParagraphStyle);

  // 处理段落边框样式
  const borderTop = finalParagraphStyle.borderTop || finalParagraphStyle.border;
  const borderRight = finalParagraphStyle.borderRight || finalParagraphStyle.border;
  const borderBottom = finalParagraphStyle.borderBottom || finalParagraphStyle.border;
  const borderLeft = finalParagraphStyle.borderLeft || finalParagraphStyle.border;

  // 只为有实际边框值的边设置样式
  const topBorder = convertToDOCXBorderStyle(borderTop);
  const bottomBorder = convertToDOCXBorderStyle(borderBottom);
  const leftBorder = convertToDOCXBorderStyle(borderLeft);
  const rightBorder = convertToDOCXBorderStyle(borderRight);

  // 处理行高：如果段落设置了固定行高但小于内部元素最大字体大小，则使用atLeast模式
  const lineHeight = finalParagraphStyle.lineHeight;
  let adjustedLineHeight = lineHeight;

  // 计算最大字体大小对应的twips值（半点单位转换为twips）
  if (lineHeight && lineHeight.lineRule === 'exact' && maxFontSize) {
    // 字体大小是半点单位，转换为twips：半点 * 10 = twips
    const maxFontSizeInTwips = maxFontSize * 10;

    // 如果固定行高小于最大字体大小，则将行高规则改为atLeast
    if (lineHeight.line < maxFontSizeInTwips) {
      adjustedLineHeight = {
        ...lineHeight,
        lineRule: 'atLeast'
      };
    }
  }

  // 处理缩进：优先使用 margin-left/right，然后是 indent
  const indentObj: any = {};
  if (finalParagraphStyle.marginLeft !== undefined) {
    indentObj.left = finalParagraphStyle.marginLeft;
  } else if (finalParagraphStyle.indent !== undefined) {
    indentObj.left = finalParagraphStyle.indent;
  }

  if (finalParagraphStyle.marginRight !== undefined) {
    indentObj.right = finalParagraphStyle.marginRight;
  }

  // 只在有边框时添加border属性
  const paragraphOptions: any = {
    children: textRuns.length > 0 ? textRuns : [new TextRun('')],
    indent: Object.keys(indentObj).length > 0 ? indentObj : undefined,
    alignment: convertToAlignmentType(finalParagraphStyle.textAlign),
    spacing: {
      ...convertToSpacing(adjustedLineHeight),
      ...(finalParagraphStyle.marginTop ? { before: finalParagraphStyle.marginTop } : {}),
      ...(finalParagraphStyle.marginBottom ? { after: finalParagraphStyle.marginBottom } : {})
    }
  };

  // 创建新的边框对象并添加到段落选项中
  const borderObj: any = {};

  if (topBorder) {
    borderObj.top = topBorder;
  }
  if (bottomBorder) {
    borderObj.bottom = bottomBorder;
  }
  if (leftBorder) {
    borderObj.left = leftBorder;
  }
  if (rightBorder) {
    borderObj.right = rightBorder;
  }

  // 只有当border对象不为空时才添加到选项中
  if (Object.keys(borderObj).length > 0) {
    paragraphOptions.border = borderObj;
  }

  return new Paragraph(paragraphOptions);
}

/**
 * 创建列表
 */
function createList(
  element: Element,
  listType: 'ul' | 'ol',
  warnings: string[],
  cssRules?: CSSRuleSet
): Paragraph[] {
  const paragraphs: Paragraph[] = [];
  const listStyle = parseInlineStyle(element, cssRules); // 顶级元素无父元素

  Array.from(element.querySelectorAll('li')).forEach((li, index) => {
    const text = (li.textContent || '').trim();
    if (text) {
      // 解析列表项样式，传入父元素以支持样式继承
      const itemInlineStyle = parseInlineStyle(li, cssRules, element);
      const finalStyle = mergeStyles(listStyle, itemInlineStyle);

      const prefix = listType === 'ol' ? `${index + 1}. ` : '• ';

      // 创建带样式的文本运行
      const textRun = new TextRun({
        text: prefix + text,
        color: finalStyle.color,
        size: finalStyle.fontSize,
        font: finalStyle.fontFamily,
        bold: finalStyle.bold,
        italics: finalStyle.italic,
        underline: finalStyle.underline ? {} : undefined,
        strike: finalStyle.strikethrough || undefined,
        scale: calculateCharacterScale(finalStyle.characterSpacing)
      });

      // 处理缩进：优先使用 margin-left/right，然后是 indent，最后加上列表默认缩进
      const indentObj: any = {};
      let leftIndent = 360; // 列表默认缩进

      if (finalStyle.marginLeft !== undefined) {
        leftIndent += finalStyle.marginLeft;
      } else if (finalStyle.indent !== undefined) {
        leftIndent += finalStyle.indent;
      }

      indentObj.left = leftIndent;

      if (finalStyle.marginRight !== undefined) {
        indentObj.right = finalStyle.marginRight;
      }

      paragraphs.push(new Paragraph({
        children: [textRun],
        indent: indentObj,
        alignment: convertToAlignmentType(finalStyle.textAlign),
        spacing: {
          ...convertToSpacing(finalStyle.lineHeight),
          ...(finalStyle.marginTop ? { before: finalStyle.marginTop } : {}),
          ...(finalStyle.marginBottom ? { after: finalStyle.marginBottom } : {})
        }
      }));
    }
  });

  if (paragraphs.length === 0) {
    warnings.push(`空的${listType}列表`);
    paragraphs.push(new Paragraph({ children: [new TextRun('')] }));
  }

  return paragraphs;
}

/**
 * 创建表格
 */
function createTable(
  element: Element,
  cssRules?: CSSRuleSet
): { table: Table | null; warnings: string[] } {
  const warnings: string[] = [];
  const tableRows: TableRow[] = [];

  // TODO: 未来可以添加表格级别的样式支持
  // const tableStyle = parseInlineStyle(element, cssRules);

  try {
    // 查找所有行（包括 thead、tbody、tfoot 中的 tr）
    const rows = element.querySelectorAll('tr');

    if (rows.length === 0) {
      warnings.push('表格中没有找到行 (tr) 元素');
      return { table: null, warnings };
    }

    Array.from(rows).forEach((row, rowIndex) => {
      const tableCells: TableCell[] = [];

      // 查找该行中的所有单元格
      const cells = row.querySelectorAll('td, th');

      if (cells.length === 0) {
        warnings.push(`第 ${rowIndex + 1} 行中没有找到单元格 (td/th) 元素`);
        return;
      }

      Array.from(cells).forEach((cell, cellIndex) => {
        // 解析单元格样式，传入父元素以支持样式继承
        const cellStyle = parseInlineStyle(cell, cssRules, row);

        // 获取单元格内容
        const cellText = (cell.textContent || '').trim();

        // 解析单元格内的文本格式
        const { textRuns } = parseTextContent(cell, cssRules, cellStyle);

        // 创建单元格段落
        const cellParagraph = new Paragraph({
          children: textRuns.length > 0 ? textRuns : [new TextRun(cellText || '')],
          alignment: convertToAlignmentType(cellStyle.textAlign),
          spacing: convertToSpacing(cellStyle.lineHeight)
        });

        // 处理单元格边框样式
        const borderTop = cellStyle.borderTop || cellStyle.border;
        const borderRight = cellStyle.borderRight || cellStyle.border;
        const borderBottom = cellStyle.borderBottom || cellStyle.border;
        const borderLeft = cellStyle.borderLeft || cellStyle.border;

        // 获取合并单元格属性
        const colspan = parseInt(cell.getAttribute('colspan') || '1', 10);
        const rowspan = parseInt(cell.getAttribute('rowspan') || '1', 10);

        // 创建表格单元格
        const tableCell = new TableCell({
          children: [cellParagraph],
          width: {
            size: 2000, // 默认宽度
            type: WidthType.DXA
          },
          // 只有在明确指定背景颜色时才添加背景
          shading: cellStyle.backgroundColor ? {
            fill: cellStyle.backgroundColor
          } : undefined,
          borders: {
            top: convertToDOCXBorderStyle(borderTop),
            bottom: convertToDOCXBorderStyle(borderBottom),
            left: convertToDOCXBorderStyle(borderLeft),
            right: convertToDOCXBorderStyle(borderRight)
          },
          // 设置合并单元格属性
          columnSpan: colspan > 1 ? colspan : undefined,
          rowSpan: rowspan > 1 ? rowspan : undefined
        });

        tableCells.push(tableCell);
      });

      if (tableCells.length > 0) {
        tableRows.push(new TableRow({ children: tableCells }));
      }
    });

    if (tableRows.length === 0) {
      warnings.push('表格中没有有效的行数据');
      return { table: null, warnings };
    }

    // 创建表格
    const table = new Table({
      rows: tableRows,
      width: {
        size: 100,
        type: WidthType.PERCENTAGE
      },
      layout: TableLayoutType.FIXED,
      // 表格边框
      borders: {
        top: { style: BorderStyle.SINGLE, size: 1, color: '000000' },
        bottom: { style: BorderStyle.SINGLE, size: 1, color: '000000' },
        left: { style: BorderStyle.SINGLE, size: 1, color: '000000' },
        right: { style: BorderStyle.SINGLE, size: 1, color: '000000' },
        insideHorizontal: { style: BorderStyle.SINGLE, size: 1, color: '000000' },
        insideVertical: { style: BorderStyle.SINGLE, size: 1, color: '000000' }
      }
    });

    return { table, warnings };
  } catch (error: any) {
    warnings.push(`表格解析错误: ${error.message}`);
    return { table: null, warnings };
  }
}

/**
 * 创建checkbox段落
 */
function createCheckbox(
  element: Element,
  cssRules?: CSSRuleSet
): Paragraph {
  // 解析 checkbox 标签的样式
  const style = parseInlineStyle(element, cssRules);

  // 获取 checkbox 的状态
  const isChecked = element.getAttribute('checked') !== undefined
                   || element.getAttribute('checked') === 'true'
                   || element.getAttribute('checked') === 'checked';

  // 获取 checkbox 的标签文本
  const label = element.getAttribute('label') || (element.textContent || '').trim() || '';

  // 创建 checkbox 符号
  const checkboxSymbol = isChecked ? '☑' : '☐';

  // 创建文本运行
  const textRun = new TextRun({
    text: `${checkboxSymbol} ${label}`,
    color: style.color,
    size: style.fontSize,
    font: style.fontFamily,
    bold: style.bold,
    italics: style.italic,
    underline: style.underline ? {} : undefined,
    strike: style.strikethrough || undefined,
    scale: calculateCharacterScale(style.characterSpacing)
  });

  // 处理缩进：优先使用 margin-left/right，然后是 indent
  const indentObj: any = {};
  if (style.marginLeft !== undefined) {
    indentObj.left = style.marginLeft;
  } else if (style.indent !== undefined) {
    indentObj.left = style.indent;
  }

  if (style.marginRight !== undefined) {
    indentObj.right = style.marginRight;
  }

  return new Paragraph({
    children: [textRun],
    indent: Object.keys(indentObj).length > 0 ? indentObj : undefined,
    alignment: convertToAlignmentType(style.textAlign),
    spacing: {
      ...convertToSpacing(style.lineHeight),
      ...(style.marginTop ? { before: style.marginTop } : {}),
      ...(style.marginBottom ? { after: style.marginBottom } : {})
    }
  });
}

/**
 * 创建页眉
 */
function createHeader(
  content: string,
  style?: {
    fontSize?: number;
    fontFamily?: string;
    color?: string;
    bold?: boolean;
    italic?: boolean;
    strikethrough?: boolean;
    alignment?: 'left' | 'center' | 'right';
  },
  cssRules?: CSSRuleSet
): Header | undefined {
  if (!content || !content.trim()) {
    return undefined;
  }

  try {
    // 使用 DOMParser 解析页眉HTML内容
    const parser = new DOMParser();
    const doc = parser.parseFromString(content, 'text/html');

    // 如果有样式设置，在HTML内容中添加样式
    if (style) {
      // 为没有明确设置text-align的元素添加对齐样式
      if (style.alignment) {
        // 为每个顶级元素添加对齐样式
        const elements = doc.querySelectorAll('p, div, span, h1, h2, h3, h4, h5, h6');
        elements.forEach((element) => {
          const currentStyle = element.getAttribute('style') || '';
          // 检查当前元素是否已经有text-align样式
          const hasTextAlign = currentStyle.includes('text-align:')
                              || currentStyle.includes('text-align :')
                              || currentStyle.includes('text-align=');

          // 只有当元素没有text-align样式时，才添加配置中的对齐样式
          if (!hasTextAlign) {
            const newStyle = currentStyle ? `${currentStyle}; text-align: ${style.alignment}` : `text-align: ${style.alignment}`;
            element.setAttribute('style', newStyle);
          }
        });
      }
    }

    // 将处理后的DOM转换回HTML字符串
    const processedContent = doc.body.innerHTML;

    // 使用 DOMParser 解析处理后的HTML内容
    const processedDoc = parser.parseFromString(processedContent, 'text/html');
    const headerChildren: Paragraph[] = [];

    // 处理页眉内容
    Array.from(processedDoc.body.children).forEach((element) => {
      const tagName = element.tagName?.toLowerCase();

      if (tagName === 'p' || tagName === 'div' || tagName === 'span') {
        const paragraph = createParagraph(element, cssRules);
        headerChildren.push(paragraph);
      } else if (tagName === 'h1' || tagName === 'h2' || tagName === 'h3'
                 || tagName === 'h4' || tagName === 'h5' || tagName === 'h6') {
        const heading = createHeading(element, tagName as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', cssRules);
        headerChildren.push(heading);
      } else {
        // 对于其他标签，创建普通段落
        const paragraph = createParagraph(element, cssRules);
        headerChildren.push(paragraph);
      }
    });

    // 如果没有解析到内容，创建一个默认段落
    if (headerChildren.length === 0) {
      const defaultStyle = style || {};
      const textRun = new TextRun({
        text: content,
        size: defaultStyle.fontSize,
        font: defaultStyle.fontFamily,
        color: defaultStyle.color,
        bold: defaultStyle.bold,
        italics: defaultStyle.italic,
        strike: defaultStyle.strikethrough || undefined
      });

      const paragraph = new Paragraph({
        children: [textRun],
        alignment: convertToAlignmentType(defaultStyle.alignment)
      });
      headerChildren.push(paragraph);
    }

    return new Header({
      children: headerChildren
    });
  } catch (error) {
    console.warn('创建页眉失败:', error);
    return undefined;
  }
}

/**
 * 创建页脚
 */
function createFooter(
  content: string,
  style?: {
    fontSize?: number;
    fontFamily?: string;
    color?: string;
    bold?: boolean;
    italic?: boolean;
    strikethrough?: boolean;
    alignment?: 'left' | 'center' | 'right';
  },
  cssRules?: CSSRuleSet
): Footer | undefined {
  if (!content || !content.trim()) {
    return undefined;
  }

  try {
    // 使用 DOMParser 解析页脚HTML内容
    const parser = new DOMParser();
    const doc = parser.parseFromString(content, 'text/html');

    // 如果有样式设置，在HTML内容中添加样式
    if (style) {
      // 为没有明确设置text-align的元素添加对齐样式
      if (style.alignment) {
        // 为每个顶级元素添加对齐样式
        const elements = doc.querySelectorAll('p, div, span, h1, h2, h3, h4, h5, h6');
        elements.forEach((element) => {
          const currentStyle = element.getAttribute('style') || '';
          // 检查当前元素是否已经有text-align样式
          const hasTextAlign = currentStyle.includes('text-align:')
                              || currentStyle.includes('text-align :')
                              || currentStyle.includes('text-align=');

          // 只有当元素没有text-align样式时，才添加配置中的对齐样式
          if (!hasTextAlign) {
            const newStyle = currentStyle ? `${currentStyle}; text-align: ${style.alignment}` : `text-align: ${style.alignment}`;
            element.setAttribute('style', newStyle);
          }
        });
      }
    }

    // 将处理后的DOM转换回HTML字符串
    const processedContent = doc.body.innerHTML;

    // 使用 DOMParser 解析处理后的HTML内容
    const processedDoc = parser.parseFromString(processedContent, 'text/html');
    const footerChildren: Paragraph[] = [];

    // 处理页脚内容
    Array.from(processedDoc.body.children).forEach((element) => {
      const tagName = element.tagName?.toLowerCase();

      if (tagName === 'p' || tagName === 'div' || tagName === 'span') {
        const paragraph = createParagraph(element, cssRules);
        footerChildren.push(paragraph);
      } else if (tagName === 'h1' || tagName === 'h2' || tagName === 'h3'
                 || tagName === 'h4' || tagName === 'h5' || tagName === 'h6') {
        const heading = createHeading(element, tagName as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', cssRules);
        footerChildren.push(heading);
      } else {
        // 对于其他标签，创建普通段落
        const paragraph = createParagraph(element, cssRules);
        footerChildren.push(paragraph);
      }
    });

    // 如果没有解析到内容，创建一个默认段落
    if (footerChildren.length === 0) {
      const defaultStyle = style || {};
      const textRun = new TextRun({
        text: content,
        size: defaultStyle.fontSize,
        font: defaultStyle.fontFamily,
        color: defaultStyle.color,
        bold: defaultStyle.bold,
        italics: defaultStyle.italic,
        strike: defaultStyle.strikethrough || undefined
      });

      const paragraph = new Paragraph({
        children: [textRun],
        alignment: convertToAlignmentType(defaultStyle.alignment)
      });
      footerChildren.push(paragraph);
    }

    return new Footer({
      children: footerChildren
    });
  } catch (error) {
    console.warn('创建页脚失败:', error);
    return undefined;
  }
}

/**
 * 创建水平分割线段落
 */
function createHorizontalRule(
  element: Element,
  cssRules?: CSSRuleSet
): Paragraph {
  // 解析 hr 标签的样式
  const style = parseInlineStyle(element, cssRules);

  // 默认的 hr 样式：顶部边框
  const defaultBorder = {
    style: 'single' as const,
    width: 15, // 1px ≈ 15 twips
    color: '000000' // 黑色
  };

  // 如果用户设置了边框样式，使用用户的设置
  const borderBottom = style.borderBottom || style.border || defaultBorder;

  // 创建带底部边框的段落，模拟 Word 中输入 --- 按回车的效果
  return new Paragraph({
    children: [new TextRun('')], // 空文本
    spacing: {
      before: 120, // 6pt 前间距
      after: 120 // 6pt 后间距
    },
    border: {
      bottom: convertToDOCXBorderStyle(borderBottom)
    }
  });
}

/**
 * 解析单个 HTML 元素
 */
async function parseElement(
  element: Element,
  warnings: string[],
  cssRules?: CSSRuleSet,
  bodyStyle?: ParsedStyle,
  options: HtmlToDocxOptions = {}
): Promise<DocumentElement[]> {
  const tagName = element.tagName?.toLowerCase();

  if (!tagName) return [];

  switch (tagName) {
    case 'h1':
    case 'h2':
    case 'h3':
    case 'h4':
    case 'h5':
    case 'h6':
      return [createHeading(element, tagName as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', cssRules)];

    case 'p': {
      // 检查 p 是否包含图片
      const hasImages = element.querySelectorAll('img').length > 0;

      if (hasImages) {
        // 如果包含图片，单独处理每个图片
        const results: DocumentElement[] = [];
        const images = element.querySelectorAll('img');

        const imagePromises = [];
        for (let i = 0; i < images.length; i += 1) {
          const img = images[i];
          imagePromises.push(createImageParagraph(img, cssRules, options));
        }

        const imageResults = await Promise.all(imagePromises);
        imageResults.forEach(result => {
          if (result.paragraph) {
            results.push(result.paragraph);
          }
          warnings.push(...result.warnings);
        });

        return results;
      }
      // 如果不包含图片，按普通段落处理
      return [createParagraph(element, cssRules, bodyStyle)];
    }

    case 'div': {
      // 检查 div 是否包含图片
      const hasImages = element.querySelectorAll('img').length > 0;

      if (hasImages) {
        // 如果包含图片，单独处理每个图片
        const results: DocumentElement[] = [];
        const images = element.querySelectorAll('img');

        const imagePromises = [];
        for (let i = 0; i < images.length; i += 1) {
          const img = images[i];
          imagePromises.push(createImageParagraph(img, cssRules, options));
        }

        const imageResults = await Promise.all(imagePromises);
        imageResults.forEach(result => {
          if (result.paragraph) {
            results.push(result.paragraph);
          }
          warnings.push(...result.warnings);
        });

        return results;
      }
      // 如果不包含图片，按普通段落处理
      return [createParagraph(element, cssRules, bodyStyle)];
    }

    case 'img': {
      const result = await createImageParagraph(element, cssRules, options);
      if (result.paragraph) {
        warnings.push(...result.warnings);
        return [result.paragraph];
      }
      warnings.push(...result.warnings);
      return [];
    }

    case 'a':
      // 链接标签单独出现时作为段落处理
      return [createParagraph(element, cssRules)];

    case 'span':
    case 'strong':
    case 'b':
    case 'em':
    case 'i':
    case 'u':
    case 'small':
    case 'big':
    case 'sub':
    case 'sup':
      // 内联元素单独出现时作为段落处理
      return [createParagraph(element, cssRules)];

    case 'ul':
    case 'ol':
      return createList(element, tagName as 'ul' | 'ol', warnings, cssRules);

    case 'table': {
      const tableResult = createTable(element, cssRules);
      warnings.push(...tableResult.warnings);
      return tableResult.table ? [tableResult.table] : [];
    }

    case 'br':
      return [new Paragraph({ children: [new TextRun('\n')] })];

    case 'hr':
      return [createHorizontalRule(element, cssRules)];

    case 'input': {
      const type = element.getAttribute('type')?.toLowerCase();
      if (type === 'checkbox') {
        return [createCheckbox(element, cssRules)];
      }
      // 其他input类型按普通段落处理
      const text = element.getAttribute('value') || element.getAttribute('placeholder') || '';
      if (text) {
        const style = parseInlineStyle(element, cssRules);
        const textRun = new TextRun({
          text,
          color: style.color,
          size: style.fontSize,
          font: style.fontFamily,
          bold: style.bold,
          italics: style.italic,
          underline: style.underline ? {} : undefined,
          strike: style.strikethrough || undefined,
          scale: calculateCharacterScale(style.characterSpacing)
        });
        return [new Paragraph({ children: [textRun] })];
      }
      return [];
    }

    case 'checkbox':
      return [createCheckbox(element, cssRules)];

    default: {
      // 对于不支持的标签，尝试提取其文本内容和样式
      const text = (element.textContent || '').trim();
      if (text) {
        warnings.push(`不支持的标签: ${tagName}, 已提取文本内容和样式`);

        const style = parseInlineStyle(element, cssRules); // 无父元素

        const textRun = new TextRun({
          text,
          color: style.color,
          size: style.fontSize,
          font: style.fontFamily,
          bold: style.bold,
          italics: style.italic,
          underline: style.underline ? {} : undefined,
          strike: style.strikethrough || undefined,
          scale: calculateCharacterScale(style.characterSpacing)
        });

        // 处理缩进：优先使用 margin-left/right，然后是 indent
        const indentObj: any = {};
        if (style.marginLeft !== undefined) {
          indentObj.left = style.marginLeft;
        } else if (style.indent !== undefined) {
          indentObj.left = style.indent;
        }

        if (style.marginRight !== undefined) {
          indentObj.right = style.marginRight;
        }

        return [new Paragraph({
          children: [textRun],
          indent: Object.keys(indentObj).length > 0 ? indentObj : undefined,
          alignment: convertToAlignmentType(style.textAlign),
          spacing: {
            ...convertToSpacing(style.lineHeight),
            ...(style.marginTop ? { before: style.marginTop } : {}),
            ...(style.marginBottom ? { after: style.marginBottom } : {})
          }
        })];
      }
      return [];
    }
  }
}

/**
 * 将 HTML 字符串转换为 DOCX 文档
 * @param html - HTML 字符串
 * @param options - 转换选项
 * @returns Promise<ConversionResult>
 */
export async function htmlToDocx(
  html: string,
  options: HtmlToDocxOptions = {}
): Promise<ConversionResult> {
  const warnings: string[] = [];

  // 使用 DOMParser 解析 HTML
  const doc = new DOMParser().parseFromString(html, 'text/html');

  // 提取所有 style 标签中的 CSS 规则
  const cssRules = extractCSSRules(doc);

  // 创建文档元素数组
  const children: DocumentElement[] = [];

  // 获取直接子元素而不是所有子元素
  // 获取直接子元素而不是所有子元素
  const bodyElement = doc.querySelector('body');
  // eslint-disable-next-line max-len
  const elementsToProcess = bodyElement ? Array.from(bodyElement.children) : Array.from(doc.documentElement.children);

  // 获取body元素的样式，用于继承
  const bodyStyle = bodyElement ? parseInlineStyle(bodyElement, cssRules) : {};

  // 并行处理所有元素
  const elementPromises = [];
  for (let i = 0; i < elementsToProcess.length; i += 1) {
    const element = elementsToProcess[i];
    elementPromises.push(parseElement(element, warnings, cssRules, bodyStyle, options));
  }

  const elementArrays = await Promise.all(elementPromises);
  elementArrays.forEach((elements) => {
    children.push(...elements);
  });

  // 创建页眉页脚
  const header = options.header?.content
    ? createHeader(options.header.content, options.header.style, cssRules)
    : undefined;
  const footer = options.footer?.content
    ? createFooter(options.footer.content, options.footer.style, cssRules)
    : undefined;

  // 创建 DOCX 文档
  const document = new Document({
    sections: [{
      children: children.length > 0 ? children : [
        new Paragraph({
          children: [new TextRun('转换的文档为空')]
        })
      ],
      headers: header ? { default: header } : undefined,
      footers: footer ? { default: footer } : undefined,
      properties: {
        page: {
          margin: {
            // 1厘米 = 28.35磅, 1磅 = 20twips
            top: Math.round((options.margins?.top || 2.54) * 28.35 * 20), // 转换为 twips
            right: Math.round((options.margins?.right || 2.54) * 28.35 * 20),
            bottom: Math.round((options.margins?.bottom || 2.54) * 28.35 * 20),
            left: Math.round((options.margins?.left || 2.54) * 28.35 * 20)
          }
        }
      }
    }],
    // 添加文档属性
    creator: options.properties?.creator,
    description: options.properties?.description,
    title: options.properties?.title,
    subject: options.properties?.subject,
    keywords: options.properties?.keywords,
    revision: options.properties?.revision,
    lastModifiedBy: options.properties?.lastModifiedBy
  });

  return {
    document,
    warnings
  };
}

/**
 * 将 DOCX 文档转换为 Buffer (Node.js) 或 Uint8Array (Browser)
 * @param document - DOCX 文档对象
 * @returns Promise<Buffer | Uint8Array>
 */
export async function docxToBuffer(document: Document): Promise<Buffer | Uint8Array> {
  const { Packer } = await import('docx');

  if (isBrowser()) {
    // 浏览器环境：使用 Blob 然后转换为 Uint8Array
    const blob = await Packer.toBlob(document);
    const arrayBuffer = await blob.arrayBuffer();
    return new Uint8Array(arrayBuffer);
  }
  // Node.js 环境：使用 Buffer
  return Packer.toBuffer(document);
}

/**
 * 简便方法：直接从 HTML 生成 DOCX Buffer
 * @param html - HTML 字符串
 * @param options - 转换选项
 * @returns Promise<{ buffer: Buffer | Uint8Array; warnings: string[] }>
 */
export async function convertHtmlToDocxBuffer(
  html: string,
  options: HtmlToDocxOptions = {}
): Promise<{ buffer: Buffer | Uint8Array; warnings: string[] }> {
  const result = await htmlToDocx(html, options);
  const buffer = await docxToBuffer(result.document);

  return {
    buffer,
    warnings: result.warnings
  };
}
